#include "head.h"

int transFile(int new_fd)
{
    train_t t;
    //发送文件名
    t.size=strlen("file1");
    strcpy(t.buf,"file1");
    send(new_fd,&t,4+t.size,0);
    //打开文件
    int fd=open("file1",O_RDONLY);
    ERROR_CHECK(fd,-1,"open");
    //发送文件大小
    struct stat file_buf;
    fstat(fd,&file_buf);
    t.size=sizeof(file_buf.st_size);
    memcpy(t.buf,&file_buf.st_size,sizeof(file_buf.st_size));
    send(new_fd,&t,4+t.size,0);

    //发送文件内容、使用sendfile
    //sendfile可以一次性发超大文件，函数内部应该有循环发送
    long ret=sendfile(new_fd,fd,NULL,file_buf.st_size);
    ERROR_CHECK(ret,-1,"sendfile");
    close(fd);
    return 0;
}

//循环接收
int recvn(int new_fd,void *pStart,int len)
{
    int total=0,ret;
    char *p=(char *)pStart;
    while(total<len)
    {
        ret=recv(new_fd,p+total,len-total,0);
        ERROR_CHECK(ret,-1,"recv");
        if(0==ret)
        {
            return -1;//对方断开了
        }
        total+=ret;
    }
    return 0;
}

//接收文件
int recvFile(int new_fd)
{
    //接文件名
    int recvLen;
    char buf[1000]={0};
    recvn(new_fd,&recvLen,4);
    recvn(new_fd,&buf,recvLen);
#ifdef DEBUG
    printf("buf=%s\n",buf);
#endif
    int fd=open(buf,O_RDWR|O_CREAT,0666);
    ERROR_CHECK(fd,-1,"open");
    //接文件大小
    off_t fileSize;
    recvn(new_fd,&recvLen,4);
    recvn(new_fd,&fileSize,recvLen);

    struct timeval start,end;//记录时间用
    gettimeofday(&start,NULL);
    //打印进度条（每百分之一）
    off_t lastSize=0;
    off_t slice=fileSize/100;//每百分之一

    //接文件内容、使用splice
    int pipefds[2];
    pipe(pipefds);
    int total=0;//已经接收的大小
    while (total<fileSize)
    {
        if(total-lastSize>slice)
        {
            printf("%5.2lf%%\r", 100.0*total/fileSize);
            fflush(stdout);//刷新标准输出
            lastSize = total;
        }
        //读4096（与接收缓冲区大小有关）个字节,写入管道
        int ret=splice(new_fd,NULL,pipefds[1],NULL,4096,SPLICE_F_MORE|SPLICE_F_NONBLOCK);
        if(ret==0)
        {
            printf("对方断开了\n");
            break;
        }
        total+=ret;
        //从管道读取数据、写入文件
        ret=splice(pipefds[0],NULL,fd,NULL,ret,SPLICE_F_MORE|SPLICE_F_NONBLOCK);
        if(ret==0)
        {
            printf("对方断开了\n");
            break;
        }
    }
    printf("100.00%%\n");
    gettimeofday(&end,NULL);
#ifdef DEBUG
    //统计下载时间
    printf("use time =%ld\n",(end.tv_sec-start.tv_sec)*1000*1000+end.tv_usec-start.tv_usec);
#endif
    close(fd);
    return 0;
}